﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Devmil.MVVM.Dependencies
{
    public class NotifyDependencyPath
    {
        public Stack<NotifyDependencyNode> Nodes { get; private set; }

        private NotifyDependencyNode TargetNode
        {
            get
            {
                if (Nodes.Count <= 0)
                    return null;
                return Nodes.Last();
            }
        }

        public object Target
        {
            get
            {
                if(TargetNode == null || !TargetNode.GetterTargetObject.IsAlive)
                    return null;
                return TargetNode.GetterTargetObject.Target;
            }
        }

        public string TargetPropertyName
        {
            get
            {
                if (TargetNode == null)
                    return null;
                return TargetNode.PropertyName;
            }
        }

        public bool IsAlive
        {
            get
            {
                return Nodes.All(n => n.IsAlive);
            }
        }

        public NotifyDependencyPath()
        {
            Nodes = new Stack<NotifyDependencyNode>();
        }

        public NotifyDependencyPath(Stack<NotifyDependencyNode> templateNodes)
            : this()
        {
            foreach (var n in templateNodes)
                Nodes.Push(n);
        }

        public void AddGetterCall(object sender, object target, string propertyName)
        {
            Nodes.Push(new NotifyDependencyNode(sender, target, propertyName));
        }

        public override string ToString()
        {
            return string.Join("->", Nodes.Select(n => n.GetterTargetObject.IsAlive ? n.PropertyName : n.PropertyName + "[Dead]").ToArray());
        }

        public override bool Equals(object obj)
        {
            if (!(obj is NotifyDependencyPath))
                return false;
            NotifyDependencyPath castedObject = (NotifyDependencyPath)obj;
            return Nodes.SequenceEqual(castedObject.Nodes);
        }

        public override int GetHashCode()
        {
            int result = 0;
            foreach (var n in Nodes)
                result ^= n.GetHashCode();
            return result;
        }
    }
}
